#ifndef unigame_Box_h
#define unigame_Box_h

#include "transform/Vector3.h"
#include "transform/Matrix.h"

namespace unigame
{
	class Box
	{
	public:
		Box():m_min(-1, -1, -1), m_max(1, 1, 1){}
		~Box(){}

		void edges(Vector3f* v);

		bool operator ==(Box& ab)
		{
			return m_min == ab.m_min && m_max == ab.m_max;
		}

		bool operator !=(Box& ab)
		{
			return m_min != ab.m_min || m_max != ab.m_max;
		}

		void addInternalPoint(float x, float y, float z);
		
		void addInternalPoint(Vector3f& v)
		{
			addInternalPoint(v.x, v.y, v.z);
		}

		bool isIntersectOrOnEdge(float x, float y, float z)
		{
			return x >= m_min.x && x <= m_max.x && y >= m_min.y && y <= m_max.y && z >= m_min.z && z <= m_max.z;
		}

		bool isIntersectOrOnEdge(Vector3f& v)
		{
			return isIntersectOrOnEdge(v.x, v.y, v.z);
		}

		bool isIntersect(float x, float y, float z)
		{
			return x > m_min.x && x < m_max.x && y > m_min.y && y < m_max.y && z > m_min.z && z < m_max.z;
		}

		bool isIntersect(Vector3f& v)
		{
			return isIntersect(v.x, v.y, v.z);
		}

		bool isIntersect(Box& ab)
		{
			return !(m_min.x >= ab.m_max.x || m_max.x <= ab.m_min.x || m_min.y >= ab.m_max.y || m_max.y <= ab.m_min.y || m_min.z >= ab.m_max.z || m_max.z <= ab.m_min.z);
		}

		bool isIntersectOrOnEdge(Box& ab)
		{
			return !(m_min.x > ab.m_max.x || m_max.x < ab.m_min.x || m_min.y > ab.m_max.y || m_max.y < ab.m_min.y || m_min.z > ab.m_max.z || m_max.z < ab.m_min.z);
		}

		bool isIntersect(Vector3f& start, Vector3f& end)
		{
			float ds = 0, de = 1;
			return isIntersect1D(start.x, end.x, m_min.x, m_max.x, ds, de) && isIntersect1D(start.y, end.y, m_min.y, m_max.y, ds, de) && isIntersect1D(start.z, end.z, m_min.z, m_max.z, ds, de);
		}

		bool isIntersectOrOnEdge(Vector3f& start, Vector3f& end)
		{
			float ds = 0, de = 1;
			return isIntersectOrOnEdge1D(start.x, end.x, m_min.x, m_max.x, ds, de) && isIntersectOrOnEdge1D(start.y, end.y, m_min.y, m_max.y, ds, de) && isIntersectOrOnEdge1D(start.z, end.z, m_min.z, m_max.z, ds, de);
		}

		void recomputeAABB(Matrixf& m, Box& box);

	private:
		bool isIntersect1D(float start, float end, float small, float big, float& deltaStart, float& deltaEnd);
		bool isIntersectOrOnEdge1D(float start, float end, float small, float big, float& deltaStart, float& deltaEnd);

		void center(Vector3f& v)
		{
			v.x = (m_min.x + m_max.x) / 2;
			v.y = (m_min.y + m_max.y) / 2;
			v.z = (m_min.z + m_max.z) / 2;
		}

	private:
		Vector3f m_min;
		Vector3f m_max;
	};
}

#endif